﻿using System;
using System.Collections.Generic;
using System.Drawing.Printing;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using OBS;
using OBS.Model;

namespace FreeAccessNetdisk.src.classes
{
    public class CloudWatcher: IWatcher
    {
        private readonly CloudClient _cloudClient;

        private string targetDir;

        public event FileChangeHandler FileChangeEvent;


        public CloudWatcher(CloudClient cloudClient, string targetDir)
        {
            _cloudClient = cloudClient;
            this.targetDir = targetDir;
        }

        public void InformFileChange(ChangeType changeType, string fileDir)
        {
            FileChangeEvent.Invoke(new ChangeFileInfo(changeType, fileDir));
        }

        //同步
        public void WatchCloudObjects(string localForderPath)//监控云端文件和本地文件的变化，以云端文件为准，给出委托
        {
            var cloudObjects = GetCloudObjects();
            var localFiles = GetLocalFiles(localForderPath);

            // 上传本地有但云端没有的文件或本地文件更新的文件
            foreach (var localFile in localFiles)
            {
                if (!cloudObjects.ContainsKey(localFile.Key))
                {
                    InformFileChange(ChangeType.DELETE, localFile.Key);
                }
            }

            // 云端有但本地没有的文件或云端文件更新的文件
            foreach (var cloudObject in cloudObjects)
            {
                if (!localFiles.ContainsKey(cloudObject.Key))//云端有本地没有
                {
                    // 需要在本地创建该文件，给出委托
                    InformFileChange(ChangeType.CREATE, cloudObject.Key);
                }
                else if (localFiles[cloudObject.Key] < cloudObjects[cloudObject.Key])
                {
                    // 如果云端文件比本地文件新，则需要更新本地文件，给出委托
                    InformFileChange(ChangeType.MODIFY, cloudObject.Key);
                }
            }
        }

        private Dictionary<string, DateTimeOffset> GetCloudObjects()//获取云端对象列表
        {
            Dictionary<string, DateTimeOffset> objects = new Dictionary<string, DateTimeOffset>();
            var cloudObjects = _cloudClient.GetObjects(); // 假设这返回了云端对象列表，包括最后修改时间
            foreach (var item in cloudObjects)
            {
                var parts = item.Split(',');
                //key是云端文件路径转换为本地相对于同步区的相对路径，lastModifiedStr是云端文件最后修改时间
                var key = parts[0].Split('=')[1].Trim().Replace('/','\\');//将云端的路径分隔符转换为本地的路径分隔符，以便与本地文件路径比较
                var lastModifiedStr = parts[1].Split('=')[1].Trim();

                // 尝试解析UTC时间戳为DateTimeOffset
                if (DateTimeOffset.TryParse(lastModifiedStr, null, System.Globalization.DateTimeStyles.AssumeUniversal, out DateTimeOffset lastModified))
                {
                    // 转换为GMT+08:00时区
                    var lastModifiedInLocal = lastModified.ToOffset(TimeSpan.FromHours(8));
                    objects.Add(key, lastModifiedInLocal);
                }
                else
                {
                    Console.WriteLine($"Failed to parse DateTimeOffset for key {key} with value {lastModifiedStr}");
                }
            }
            return objects;
        }


        private Dictionary<string, DateTime> GetLocalFiles(string localForderPath)//获取本地文件列表
        {
            Dictionary<string, DateTime> files = new Dictionary<string, DateTime>();
            var allFiles = Directory.GetFiles(localForderPath, "*.*", SearchOption.AllDirectories);
            foreach (var file in allFiles)
            {
                var info = new FileInfo(file);
                string relativePath = file.Substring(localForderPath.Length).TrimStart('\\');
                DateTime lastModified = info.LastWriteTime;
                //relativePath是本地文件路径相对于同步区的相对路径，lastModified是本地文件最后修改时间
                files.Add(relativePath, lastModified);
            }
            return files;
        }

        public void StartWatcher()
        {
            WatchCloudObjects(this.targetDir);
        }

        public void StopWatcher()
        {
            
        }

        public void SetTarget(string targetDir)
        {
            this.targetDir = targetDir;
        }
    }
}
